home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / magazi~1 / 226 / analog.49 / f6.ca < prev    next >
Encoding:
Text File  |  1986-10-14  |  15.3 KB  |  429 lines

  1. /*****************************************************************
  2. *
  3. * f6.ca: special routines for screen dump ops:
  4. *        part 1 of 3.
  5. *
  6. *
  7. ******************************************************************/
  8.  
  9.  
  10. /****
  11. *
  12. * explode-- generate a list of scan-line slices from the contents of
  13. *           a character cell.
  14. *
  15. *           also calculate and return hash value for
  16. *           the pattern processed.
  17. *
  18. *           WARNING: 'explode' must be used on font forms only.
  19. *
  20. *    at entry:
  21. *              (a6) +  8 -> ascii code of char to explode.
  22. *              (a6) + 12 -> pointer to font header desired.
  23. *              (a6) + 16 -> area in which to save scan line values.
  24. *
  25. *    at exit:
  26. *              returns hash value in d7,
  27. *              next 'scan_pack' space in a0.
  28. *              all other registers preserved.
  29. *
  30. *
  31. ****/
  32. explode:
  33.           link      A6,#0               ;frame pointer
  34.           movem.l   D0-D6/A1-A5,-(A7)   ;save everything
  35.  
  36.           movea.l   16(A6),A1           ;pointer for storing scan lines
  37.           movea.l   12(A6),A5           ;get font header pointer
  38.           move.l    8(A6),D5            ;ascii code of char
  39.           move.l    #0,D1               ;clear registers-- quickly
  40.           move.l    #0,D2
  41.           move.l    #0,D3
  42.           move.l    #0,D4
  43.           move.l    #0,D6
  44.           move.l    #0,D7
  45.           
  46.           movea.l   CHAR_OFFTAB(A5),A4  ;get base of char offset table
  47.           move.w    FORM_HEIGHT(A5),D2  ;get char height (scan lines)
  48.           movea.l   FONT_DATA(A5),A0    ;get start of actual font data
  49.           move.w    FORM_WIDTH(A5),D1   ;get scan line length
  50.           move.w    BIG_WIDTH(A5),D4    ;get char (vice char cell) width
  51.  
  52.           lsl.l     #1,D5               ; * 2 for word index          
  53.           move.w    0(A4,D5.l),D3       ;get char offset val
  54.  
  55. /* now calculate char position in bit table       */
  56.           divu      #BYTESIZE,D3        ;offset / bytesize in d3.w
  57.           move.w    D3,-(A7)            ;save it
  58.           move.w    #0,-(A7)            ;make it a long when it comes back
  59.           lsr.l     #BYTESIZE,D3
  60.           lsr.l     #BYTESIZE,D3        ;offset % bytesize in d3.w
  61.           adda.l    (A7)+,A0            ;get byte address in font data
  62.  
  63. /* a0 == byte address in font data table, d3 == bit offset, if any   */
  64. /*       now calculate char mask into d5                             */
  65.           clr.l     D5                  ;clear mask reg
  66.           move.l    #-1,-(A7)           ;no invert
  67.           bsr       slice_and_hash      ;get slices and hash values
  68.           addq.l    #4,A7               ;pop arg
  69.           movea.l   A1,A0               ;return scan pack next pointer
  70.  
  71.           movem.l   (A7)+,D0-D6/A1-A5   ;restore registers
  72.           unlk      A6                  ;deallocate frame pointer
  73.           rts
  74.  
  75.  
  76. /****
  77. *
  78. * hash_char-- count each set pixel in a char cell, assigning to
  79. *             each pixel a unique number based on matrix position
  80. *             in the cell.
  81. *
  82. *    at entry:
  83. *              d0.b == char data
  84. *              d2   == current scan line (counting down)
  85. *              d4   == char width
  86. *
  87. *    at exit:
  88. *              d7 == intermediate hash value
  89. *              all other registers preserved
  90. *
  91. *
  92. ****/
  93. hash_char:
  94.           movem.l   D0-D3/D4,-(A7)      ;save registers
  95.  
  96.           mulu      D4,D2               ;width * line == hash base
  97.           clr.l     D1                  ;hash counter   
  98.           clr.l     D3                  ;running total         
  99.           bra.s     hash_test           ;start           
  100. hash_loop:
  101.           addq.l    #1,D1               ;inc counter
  102.           lsl.b     #1,D0               ;get a bit
  103.           bcc.s     hash_test           ;if zero, continue
  104.           move.l    D2,-(A7)            ;else save hash base
  105.           add.l     D1,D2               ;get unique number this bit
  106.           add.l     D2,D3               ;add to total
  107.           move.l    (A7)+,D2            ;restore hash base
  108. hash_test:
  109.           dbf       D4,hash_loop        ;get all the data
  110.  
  111.           move.l    D3,D7               ;save result
  112.  
  113.           movem.l   (A7)+,D0-D3/D4      ;restore registers
  114.           rts
  115.  
  116.  
  117. /****
  118. *
  119. * setup_hash-- set up hash table for a given font.
  120. *
  121. *    at entry:
  122. *              (a6) +  8 -> font header pointer.
  123. *
  124. *    at exit:
  125. *              all registers preserved.
  126. *
  127. *
  128. ****/
  129. setup_hash:
  130.           link           A6,#0               ;frame pointer
  131.           movem.l        A0-A2/A4/D0/D7,-(A7)   ;save registers
  132.           move.l         #-1,D0              ;get a4
  133.           bsr            reg_a4              ;do it
  134.           movea.l        scan_packs(A4),A2   ;start of collision space
  135.           movea.l        hash_table(A4),A1   ;start of hash table
  136.           move.l         #0,D0               ;first ascii code
  137.  
  138. s_hash_loop:
  139.           move.l         #-1,(A2)            ;init 'next' fld this pack
  140.           pea            6(A2)               ;push data part this pack
  141.           move.l         8(A6),-(A7)         ;font header pointer
  142.           move.l         D0,-(A7)            ;ascii code
  143.           bsr            explode             ;get hash val, &c.
  144.           adda.l         #12,A7              ;pop args
  145.  
  146. /* d7 == hash val                                      */
  147. /* a0 == next free 'scan_packs' space, if needed       */
  148.           mulu           #HASH_IX,D7         ;get hash index
  149.           tst.l          2(A1,D7.l)          ;test 'use' field
  150.           bmi            not_used            ;if not used
  151.           move.l         D0,-(A7)            ;else push ascii code
  152.           pea            0(A1,D7.l)          ;push 'hash_table' pos
  153.           move.l         A2,-(A7)            ;push 'scan_pack' address
  154.           bsr            collide             ;insert into collision list
  155.           adda.l         #12,A7              ;pop args
  156.           movea.l        A0,A2               ;next 'scan_pack' space
  157.           bra            hash_next           ;and continue
  158. not_used:
  159.           move.w         D0,0(A1,D7.l)       ;store code
  160.           move.l         #NULL,2(A1,D7.l)    ;but no collision list yet
  161.  
  162. hash_next:
  163.           addq.l         #1,D0               ;next ascii code
  164.           cmp.l          #HASH_SIZE,D0       ;finished?
  165.           beq.s          hash_exit           ;if so
  166.           bra            s_hash_loop         ;else continue
  167. hash_exit:
  168.           movem.l        (A7)+,A0-A2/A4/D0/D7   ;restore registers
  169.           unlk           A6                  ;deallocate frame
  170.           rts
  171.  
  172.  
  173. /****
  174. *
  175. * collide-- insert pointer to 'scan_pack' into the collision list
  176. *           of a hash table element or begin the collision list.
  177. *
  178. *    at entry:
  179. *              (a6) +  8 ->   'scan_pack' address.
  180. *              (a6) + 12 ->   'hash_table' element address.
  181. *              (a6) + 16 ->   ascii code.
  182. *
  183. *    at exit:
  184. *              all registers preserved.
  185. *
  186. *
  187. ****/
  188. collide:
  189.           link           A6,#0          ;frame pointer
  190.           movem.l        A0-A1/D0,-(A7) ;save registers
  191.  
  192.           move.l         16(A6),D0      ;get ascii code
  193.           movea.l        8(A6),A0       ;'scan_pack' address
  194.           movea.l        12(A6),A1      ;'hash_table' element address
  195.           tst.l          2(A1)          ;test 'use' field
  196.           bne            add_list       ;if list already started
  197.           move.l         A0,2(A1)       ;else insert pointer to 'scan_pack'
  198.           move.w         D0,4(A0)       ;store ascii code
  199.           bra            collide_exit   ;and leave
  200.  
  201. add_list:
  202.           movea.l        2(A1),A1       ;get pointer to head of list
  203. looking:
  204.           tst.l          (A1)           ;test 'next' field
  205.           bmi            found_it       ;if == -1, then end found
  206.           movea.l        (A1),A1        ;else get next pointer
  207.           bra            looking        ;and keep going
  208. found_it:
  209.           move.l         A0,(A1)        ;insert pointer to 'scan_pack'
  210.           move.w         D0,4(A0)       ;store ascii code into 'scan_pack'
  211. collide_exit:
  212.           movem.l        (A7)+,A0-A1/D0 ;restore registers
  213.           unlk           A6             ;deallocate frame
  214.           rts
  215.  
  216.  
  217. /****
  218. *
  219. * find_collide-- find a matching set of scan lines in a collision list.
  220. *
  221. *    at entry:
  222. *              (a6) +  8 -> first 'scan_pack' pointer.
  223. *              (a6) + 12 -> scan line list to be matched.
  224. *
  225. *    at exit:
  226. *              d0 contains ascii code of matched character, or 0
  227. *                 if error.
  228. *
  229. *
  230. ****/
  231. find_collide:
  232.           link           A6,#0               ;frame pointer
  233.           movem.l        D1-D3/A0-A1,-(A7)   ;save registers
  234.  
  235.           movea.l        8(A6),A0            ;'scan_pack' list
  236.           movea.l        12(A6),A1           ;scan line list address
  237.  
  238. collide_loop:
  239.           move.l         A0,D2               ;save base pointer
  240.           lea.l          6(A0),A0            ;get start of data
  241. find_c_loop:
  242.           cmpm.b         (A0)+,(A1)+         ;compare lines
  243.           bne            c_no_match          ;no match => go to next
  244.           cmpi.b         #BORDER,(A0)        ;end of data?
  245.           beq            c_good_match        ;if so
  246.           bra            find_c_loop         ;else keep going
  247. c_no_match:
  248.           movea.l        D2,A0               ;recover base pointer
  249.           tst.l          (A0)                ;was that the last one?
  250.           bmi            f_coll_error        ;if so
  251.           movea.l        (A0),A0             ;else get pointer
  252.           movea.l        12(A6),A1           ;reset scan list pointer
  253.           bra            collide_loop        ;and continue
  254.  
  255. c_good_match:
  256.           movea.l        D2,A0               ;recover base pointer
  257.           clr.l          D0
  258.           move.w         4(A0),D0            ;get ascii code
  259.  
  260. f_coll_exit:
  261.           movem.l        (A7)+,D1-D3/A0-A1   ;restore registers
  262.           unlk           A6                  ;deallocate frame
  263.           rts
  264.  
  265. f_coll_error:
  266.           move.l         #0,D0               ;error code
  267.           bra            f_coll_exit         ;and leave
  268.  
  269.  
  270. /****          
  271. *
  272. * match_lists-- compare two scan lists.
  273. *
  274. *    at entry:
  275. *              (a6) +  8 -> one scan list.
  276. *              (a6) + 12 -> the other scan list.
  277. *
  278. *    at exit:
  279. *              d0 contains -1 if no match; else 1.
  280. *
  281. *
  282. ****/
  283. match_lists:
  284.           link      A6,#0                    ;frame pointer
  285.           movem.l   A0-A1,-(A7)
  286.  
  287.           movea.l   8(A6),A0                 ;one cell list
  288.           movea.l   12(A6),A1                ;the other list
  289. zm_l_loop:
  290.           cmpm.b    (A0)+,(A1)+              ;compare one line
  291.           bne       zm_l_nomatch
  292.           cmpi.b    #BORDER,(A0)             ;end of data?
  293.           beq       zm_l_goodmatch           ;if so
  294.           bra       zm_l_loop
  295. zm_l_nomatch:
  296.           move.l    #-1,D0                   ;fail code
  297.           bra       zm_l_exit                ;and leave
  298. zm_l_goodmatch:
  299.           move.l    #1,D0                    ;success code
  300. zm_l_exit:
  301.           movem.l   (A7)+,A0-A1        
  302.           unlk      A6
  303.           rts
  304.  
  305.  
  306. /****
  307. *
  308. * make_slices-- from a byte address and a bit offset, return the
  309. *               contents of the current char cell in the form of
  310. *               a list of scan-line values, and calculate a hash
  311. *               value.
  312. *
  313. *    at entry:
  314. *              (a6) +  8 -> byte address of current cell.
  315. *              (a6) + 12 -> font header.
  316. *              (a6) + 16 -> area in which to save scan line data.
  317. *              (a6) + 20 -> bit offset.
  318. *              (a6) + 24 -> scan line length.
  319. *              (a6) + 28 -> invert flag.
  320. *
  321. *    at exit:
  322. *              d0 == 0 if no set pixels in this cell, else != 0.
  323. *              d7 == hash value.
  324. *              all other registers preserved.
  325. *
  326. *
  327. ****/
  328. make_slices:
  329.           link      A6,#0               ;frame pointer
  330.           movem.l   D1-D6/A0-A1/A4/A5,-(A7)
  331.           
  332.           movea.l   8(A6),A0            ;cell address
  333.           movea.l   12(A6),A5           ;font header
  334.           movea.l   16(A6),A1           ;save area
  335.  
  336.           move.l    #0,D1               ;clear registers quickly
  337.           move.l    #0,D2
  338.           move.l    #0,D3
  339.           move.l    #0,D4
  340.           move.l    #0,D5
  341.           move.l    #0,D6
  342.           move.l    #0,D7
  343.  
  344.           move.w    FORM_HEIGHT(A5),D2  ;char height
  345.           move.l    24(A6),D1           ;scan length
  346.           move.w    BIG_WIDTH(A5),D4    ;char width
  347.           move.l    20(A6),D3           ;bit offset
  348.  
  349.           move.l    28(A6),-(A7)        ;push invert flag
  350.           bsr       slice_and_hash      ;get slices and hash value
  351.           addq.l    #4,A7               ;pop arg
  352.  
  353.           move.l    D6,D0               ;return flag
  354.           movem.l   (A7)+,D1-D6/A0-A1/A4/A5
  355.           unlk      A6
  356.           rts
  357.  
  358.  
  359. /****
  360. *
  361. * slice_and_hash-- generate a list of scan-line slices from a memory
  362. *                  cell and calculate a hash value for the list.
  363. *                  (called by 'explode' and 'make_slices').
  364. *
  365. *    at entry:
  366. *              (a6) + 8 -> invert flag: 0 => invert, else don't.
  367. *
  368. *              (a0) -> start of data cell.
  369. *              (a1) -> start of list storage area.
  370. *
  371. *              d0 is cleared (receives char data).
  372. *              d1 == scan length.
  373. *              d2 == scan line count (char height).
  374. *              d3 == bit offset of data cell.
  375. *              d4 == char width.
  376. *              d5 is cleared (used for char data mask).
  377. *              d6 is cleared (used for pixel-set flag).
  378. *              d7 is cleared (used for hash value).
  379. *
  380. *    at exit:
  381. *              (a1) -> next byte after scan list space used.
  382. *              d6 == 0 if no set pixels this cell, else != 0.
  383. *              d7 == hash value.
  384. *
  385. *
  386. ****/
  387. slice_and_hash:
  388.           link      A6,#0               ;frame pouinter
  389.           clr.l     D6                  ;clear pixel-set flag
  390.           bra       m_sl_test           ;now go
  391.  
  392. m_sl_loop:
  393.           clr.l     D0
  394.           move.b    0(A0),D0            ;get byte
  395.           tst.l     8(A6)               ;invert?
  396.           bne.s     h_s_next            ;if not
  397.           not.b     D0                  ;else take one's complement
  398.  
  399. h_s_next:
  400.           move.b    D0,(A1)+            ;save it
  401.  
  402.           move.l    D7,-(A7)            ;save current hash val
  403.           bsr       hash_char           ;calc intermediate val
  404.           add.l     (A7)+,D7            ;add to total
  405.  
  406.           tst.b     D0                  ;test for set pixels
  407.           beq.s     m_sl_nxt            ;if no set pixels
  408.           move.l    #1,D6               ;else set flag    
  409. m_sl_nxt:
  410.           adda.l    D1,A0               ;next line
  411. m_sl_test:
  412.           dbf       D2,m_sl_loop        ;continue
  413.  
  414. /* WARNING: '.w' length used here to cheat on address alignment--  */
  415. /*   value of d2 above should be explicitly checked to see if this */
  416. /*   is necessary                                                  */
  417.           move.b    #BORDER,(A1)+       ;end marker
  418.           move.b    #BORDER,(A1)+       ;aligned
  419.           divu      #HASH_SIZE,D7       ;finalize hash value
  420.           lsr.l     #BYTESIZE,D7
  421.           lsr.l     #BYTESIZE,D7
  422.           unlk      A6                  ;deallocate frame
  423.           rts                           ;dummy comment
  424.  
  425.  
  426.  
  427.  
  428.  
  429.